// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.ai.states;

import java.util.HashMap;
import org.joml.Vector3f;
import zombie.ai.State;
import zombie.audio.parameters.ParameterZombieState;
import zombie.characters.IsoGameCharacter;
import zombie.characters.IsoZombie;
import zombie.core.skinnedmodel.advancedanimation.AnimEvent;
import zombie.gameStates.IngameState;
import zombie.iso.IsoChunk;
import zombie.iso.IsoDirections;
import zombie.iso.IsoWorld;
import zombie.iso.Vector2;
import zombie.network.GameServer;
import zombie.network.ServerMap;
import zombie.util.Type;
import zombie.vehicles.PolygonalMap2;

public final class WalkTowardState extends State {
    private static final WalkTowardState _instance = new WalkTowardState();
    private static final Integer PARAM_IGNORE_OFFSET = 0;
    private static final Integer PARAM_IGNORE_TIME = 1;
    private static final Integer PARAM_TICK_COUNT = 2;
    private final Vector2 temp = new Vector2();
    private final Vector3f worldPos = new Vector3f();

    public static WalkTowardState instance() {
        return _instance;
    }

    @Override
    public void enter(IsoGameCharacter owner) {
        HashMap hashMap = owner.getStateMachineParams(this);
        if (hashMap.get(PARAM_IGNORE_OFFSET) == null) {
            hashMap.put(PARAM_IGNORE_OFFSET, Boolean.FALSE);
            hashMap.put(PARAM_IGNORE_TIME, 0L);
        }

        if (hashMap.get(PARAM_IGNORE_OFFSET) == Boolean.TRUE && System.currentTimeMillis() - (Long)hashMap.get(PARAM_IGNORE_TIME) > 3000L) {
            hashMap.put(PARAM_IGNORE_OFFSET, Boolean.FALSE);
            hashMap.put(PARAM_IGNORE_TIME, 0L);
        }

        hashMap.put(PARAM_TICK_COUNT, IngameState.instance.numberTicks);
        if (((IsoZombie)owner).isUseless()) {
            owner.changeState(ZombieIdleState.instance());
        }

        owner.getPathFindBehavior2().walkingOnTheSpot.reset(owner.x, owner.y);
        ((IsoZombie)owner).networkAI.extraUpdate();
    }

    @Override
    public void execute(IsoGameCharacter owner) {
        HashMap hashMap = owner.getStateMachineParams(this);
        IsoZombie isoZombie = (IsoZombie)owner;
        if (!isoZombie.bCrawling) {
            owner.setOnFloor(false);
        }

        IsoGameCharacter isoGameCharacter = Type.tryCastTo(isoZombie.target, IsoGameCharacter.class);
        if (isoZombie.target != null) {
            if (isoZombie.isTargetLocationKnown()) {
                if (isoGameCharacter != null) {
                    isoZombie.getPathFindBehavior2().pathToCharacter(isoGameCharacter);
                    if (isoGameCharacter.getVehicle() != null && isoZombie.DistToSquared(isoZombie.target) < 16.0F) {
                        Vector3f vector3f = isoGameCharacter.getVehicle().chooseBestAttackPosition(isoGameCharacter, isoZombie, this.worldPos);
                        if (vector3f == null) {
                            isoZombie.setVariable("bMoving", false);
                            return;
                        }

                        if (Math.abs(owner.x - isoZombie.getPathFindBehavior2().getTargetX()) > 0.1F
                            || Math.abs(owner.y - isoZombie.getPathFindBehavior2().getTargetY()) > 0.1F) {
                            isoZombie.setVariable("bPathfind", true);
                            isoZombie.setVariable("bMoving", false);
                            return;
                        }
                    }
                }
            } else if (isoZombie.LastTargetSeenX != -1
                && !owner.getPathFindBehavior2()
                    .isTargetLocation((float)isoZombie.LastTargetSeenX + 0.5F, (float)isoZombie.LastTargetSeenY + 0.5F, (float)isoZombie.LastTargetSeenZ)) {
                owner.pathToLocation(isoZombie.LastTargetSeenX, isoZombie.LastTargetSeenY, isoZombie.LastTargetSeenZ);
            }
        }

        if (owner.getPathTargetX() == (int)owner.getX() && owner.getPathTargetY() == (int)owner.getY()) {
            if (isoZombie.target == null) {
                isoZombie.setVariable("bPathfind", false);
                isoZombie.setVariable("bMoving", false);
                return;
            }

            if ((int)isoZombie.target.getZ() != (int)owner.getZ()) {
                isoZombie.setVariable("bPathfind", true);
                isoZombie.setVariable("bMoving", false);
                return;
            }
        }

        boolean boolean0 = owner.isCollidedWithVehicle();
        if (isoGameCharacter != null && isoGameCharacter.getVehicle() != null && isoGameCharacter.getVehicle().isCharacterAdjacentTo(owner)) {
            boolean0 = false;
        }

        boolean boolean1 = owner.isCollidedThisFrame();
        if (boolean1 && hashMap.get(PARAM_IGNORE_OFFSET) == Boolean.FALSE) {
            hashMap.put(PARAM_IGNORE_OFFSET, Boolean.TRUE);
            hashMap.put(PARAM_IGNORE_TIME, System.currentTimeMillis());
            float float0 = isoZombie.getPathFindBehavior2().getTargetX();
            float float1 = isoZombie.getPathFindBehavior2().getTargetY();
            float float2 = isoZombie.z;
            boolean1 = !this.isPathClear(owner, float0, float1, float2);
        }

        if (!boolean1 && !boolean0) {
            this.temp.x = isoZombie.getPathFindBehavior2().getTargetX();
            this.temp.y = isoZombie.getPathFindBehavior2().getTargetY();
            this.temp.x = this.temp.x - isoZombie.getX();
            this.temp.y = this.temp.y - isoZombie.getY();
            float float3 = this.temp.getLength();
            if (float3 < 0.25F) {
                owner.x = isoZombie.getPathFindBehavior2().getTargetX();
                owner.y = isoZombie.getPathFindBehavior2().getTargetY();
                owner.nx = owner.x;
                owner.ny = owner.y;
                float3 = 0.0F;
            }

            if (float3 < 0.025F) {
                isoZombie.setVariable("bPathfind", false);
                isoZombie.setVariable("bMoving", false);
            } else {
                if (!GameServer.bServer && !isoZombie.bCrawling && hashMap.get(PARAM_IGNORE_OFFSET) == Boolean.FALSE) {
                    float float4 = Math.min(float3 / 2.0F, 4.0F);
                    float float5 = (float)((owner.getID() + isoZombie.ZombieID) % 20) / 10.0F - 1.0F;
                    float float6 = (float)((isoZombie.getID() + isoZombie.ZombieID) % 20) / 10.0F - 1.0F;
                    this.temp.x = this.temp.x + isoZombie.getX();
                    this.temp.y = this.temp.y + isoZombie.getY();
                    this.temp.x += float5 * float4;
                    this.temp.y += float6 * float4;
                    this.temp.x = this.temp.x - isoZombie.getX();
                    this.temp.y = this.temp.y - isoZombie.getY();
                }

                isoZombie.bRunning = false;
                this.temp.normalize();
                if (isoZombie.bCrawling) {
                    if (isoZombie.getVariableString("TurnDirection").isEmpty()) {
                        isoZombie.setForwardDirection(this.temp);
                    }
                } else {
                    isoZombie.setDir(IsoDirections.fromAngle(this.temp));
                    isoZombie.setForwardDirection(this.temp);
                }

                if (owner.getPathFindBehavior2().walkingOnTheSpot.check(owner.x, owner.y)) {
                    owner.setVariable("bMoving", false);
                }

                long _long = (Long)hashMap.get(PARAM_TICK_COUNT);
                if (IngameState.instance.numberTicks - _long == 2L) {
                    isoZombie.parameterZombieState.setState(ParameterZombieState.State.Idle);
                }
            }
        } else {
            isoZombie.AllowRepathDelay = 0.0F;
            isoZombie.pathToLocation(owner.getPathTargetX(), owner.getPathTargetY(), owner.getPathTargetZ());
            if (!isoZombie.getVariableBoolean("bPathfind")) {
                isoZombie.setVariable("bPathfind", true);
                isoZombie.setVariable("bMoving", false);
            }
        }
    }

    @Override
    public void exit(IsoGameCharacter owner) {
        owner.setVariable("bMoving", false);
        ((IsoZombie)owner).networkAI.extraUpdate();
    }

    @Override
    public void animEvent(IsoGameCharacter owner, AnimEvent event) {
    }

    @Override
    public boolean isMoving(IsoGameCharacter owner) {
        return true;
    }

    private boolean isPathClear(IsoGameCharacter isoGameCharacter, float float0, float float1, float float2) {
        int int0 = (int)float0 / 10;
        int int1 = (int)float1 / 10;
        IsoChunk isoChunk = GameServer.bServer
            ? ServerMap.instance.getChunk(int0, int1)
            : IsoWorld.instance.CurrentCell.getChunkForGridSquare((int)float0, (int)float1, (int)float2);
        if (isoChunk != null) {
            int int2 = 1;
            int2 |= 2;
            return !PolygonalMap2.instance
                .lineClearCollide(
                    isoGameCharacter.getX(),
                    isoGameCharacter.getY(),
                    float0,
                    float1,
                    (int)float2,
                    isoGameCharacter.getPathFindBehavior2().getTargetChar(),
                    int2
                );
        } else {
            return false;
        }
    }

    public boolean calculateTargetLocation(IsoZombie zomb, Vector2 location) {
        assert zomb.isCurrentState(this);

        HashMap hashMap = zomb.getStateMachineParams(this);
        location.x = zomb.getPathFindBehavior2().getTargetX();
        location.y = zomb.getPathFindBehavior2().getTargetY();
        this.temp.set(location);
        this.temp.x = this.temp.x - zomb.getX();
        this.temp.y = this.temp.y - zomb.getY();
        float float0 = this.temp.getLength();
        if (float0 < 0.025F) {
            return false;
        } else if (!GameServer.bServer && !zomb.bCrawling && hashMap.get(PARAM_IGNORE_OFFSET) == Boolean.FALSE) {
            float float1 = Math.min(float0 / 2.0F, 4.0F);
            float float2 = (float)((zomb.getID() + zomb.ZombieID) % 20) / 10.0F - 1.0F;
            float float3 = (float)((zomb.getID() + zomb.ZombieID) % 20) / 10.0F - 1.0F;
            location.x += float2 * float1;
            location.y += float3 * float1;
            return true;
        } else {
            return false;
        }
    }
}
